﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;

namespace Bzure.Common.Composition
{
    public abstract class MEFContainerBase
    {
        protected virtual CompositionContainer CreateCompositionContainer(IEnumerable<ComposablePartCatalog> catalogItems = default (IEnumerable<ComposablePartCatalog>))
        {
            var catalog = new AggregateCatalog();
            if (catalogItems != default(IEnumerable<ComposablePartCatalog>))
            {
                catalogItems.ForEach(item =>
                {
                    catalog.Catalogs.Add(item);
                });
            }
            catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            string binPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin");
            if (!Directory.Exists(binPath))
            {
                Directory.CreateDirectory(binPath);
            }
            catalog.Catalogs.Add(new DirectoryCatalog(binPath));

            string basePath = AppDomain.CurrentDomain.BaseDirectory;
            basePath = basePath.Remove(basePath.Length - 1, 1);
            catalog.Catalogs.Add(new DirectoryCatalog(basePath));

            //catalog.Catalogs.Add(new DirectoryCatalog(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Comp")));

            //var config = CompositionConfigurationSection.GetInstance();
            //if (config != null && config.Catalogs != null)
            //{
            //    config.Catalogs
            //        .Cast<CatalogConfigurationElement>()
            //        .ForEach(c =>
            //        {
            //            if (!string.IsNullOrEmpty(c.Path))
            //            {
            //                string path = c.Path;
            //                if (path.StartsWith("~"))
            //                    path = MapPath(path);

            //                foreach (var directoryCatalog in GetDirectoryCatalogs(path))
            //                {

            //                    // Register our path for probing.
            //                    RegisterPath(directoryCatalog.FullPath);

            //                    // Add the catalog.
            //                    catalog.Catalogs.Add(directoryCatalog);
            //                }
            //            }
            //        });
            //}

            var provider = new DynamicInstantiationExportProvider();
            var container = new CompositionContainer(catalog, provider);
            provider.SourceProvider = container;

            return container;
        }

        //private void RegisterPath(string path)
        //{
        //    AppDomain.CurrentDomain.AppendPrivatePath(path);
        //}
        public virtual void Compose(IEnumerable<ComposablePartCatalog> catalogItems = default (IEnumerable<ComposablePartCatalog>))
        {
            var container = CreateCompositionContainer(catalogItems);
            if (container == null)
                return;

              container.ComposeParts(this);
        }
        protected IEnumerable<DirectoryCatalog> GetDirectoryCatalogs(string path)
        {

            List<DirectoryCatalog> list = new List<DirectoryCatalog>();
            list.Add(new DirectoryCatalog(path));

            list.AddRange(
                Directory.GetDirectories(path).Select(directory => new DirectoryCatalog(directory)));

            return list;
        }
        //protected abstract string MapPath(string virtualPath);
    }
}
